﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Reflection;
using System.Windows.Interop;
using System.Threading;
using WindowPlace.Common;


namespace WindowPlace
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        #region Fields

        public static int MOD_ALT = 0x1;
        public static int MOD_CONTROL = 0x2;
        public static int MOD_SHIFT = 0x4;
        public static int MOD_WIN = 0x8;
        public static int WM_HOTKEY = 0x312;

        #endregion

        private PlaceProfileNotifier notifier = new PlaceProfileNotifier();

        #region Constructor

        static MainWindow()
        {
            InitCommands();
        }

        public MainWindow()
        {
            InitializeComponent();

            //_hookID = KeyHook.SetHook(keyboardcallback);


            //RegisterHotKey(Keys.B | Keys.Alt);


            notifier.Show();

            App.Current.MainWindow = this;

            notifier.HidingMilliseconds = 200;
            notifier.OpeningMilliseconds = 200;
            notifier.StayOpenMilliseconds = 1000;

            this.SettingsFilename = (string)WindowPlace.Properties.Settings.Default["SettingsFilename"];

            this.Settings = WindowPlaceSettings.Load(SettingsFilename);
            this.Settings.HotKeyCombinationChanged += new EventHandler(Settings_HotKeyCombinationChanged);
            this.HotKeyCombinationString = string.Format("{0}{1}{2}", Settings.PlusShift ? "Shift" : string.Empty, Settings.PlusControl ? Settings.PlusShift ? "+Control" : "Control" : string.Empty, Settings.PlusAlt ? Settings.PlusShift | Settings.PlusControl ? "+Alt" : "Alt" : string.Empty);
            this.Settings.Version = Assembly.GetExecutingAssembly().GetName().Version;
            this.PlaceProfiles = new ObservableCollection<PlaceProfile>(this.Settings.PlaceProfiles);
            this.DataContext = this;

            this.WindowCaptionsList.ItemsSource = WindowPlace.Common.Helper.GetWindowInfos().Where(a => a.IsUseful && a.IsVisible == true).OrderBy(b => b.Caption);

            RegisterHotKeys();

        }

        void Settings_HotKeyCombinationChanged(object sender, EventArgs e)
        {
            this.HotKeyCombinationString = string.Format("{0}{1}{2}", Settings.PlusShift ? "Shift" : string.Empty, Settings.PlusControl ? Settings.PlusShift ? "+Control" : "Control" : string.Empty, Settings.PlusAlt ? Settings.PlusShift | Settings.PlusControl ? "+Alt" : "Alt" : string.Empty);
            RegisterHotKeys();
        }

        //private static int keyId;
        private static List<int> HotKeyIds = new List<int>();
        private static Random random = new Random(100);


        void ComponentDispatcher_ThreadPreprocessMessage(ref MSG msg, ref bool handled)
        {
            //Debug.Print("msg.Message = {0}", msg.message);
            if (msg.message == WM_HOTKEY)
            {
                //Debug.Print("rEGISTERED hOTkEY PRESSED {0}    {1}", msg.lParam, msg.wParam);
                Int32 lParam = msg.lParam.ToInt32();
                int hiword = Helper.HiWord(lParam);
                int loword = Helper.LoWord(lParam);
                Keys keys = (Keys)hiword;
                //Debug.Print(String.Format("High word = {0:x}, Low word = {1:x} Key = {2}", hiword, loword, keys));
                PlaceProfile currentlyselectedprofile = SelectedPlaceProfile;
                SelectedPlaceProfile = this.PlaceProfiles[Helper.NumericKeyToInteger(hiword) - 1];
                if (currentlyselectedprofile == SelectedPlaceProfile)
                {
                    //Debug.Print("reapplying protocol");
                    NavigationCommands.Refresh.Execute(SelectedPlaceProfile, this);
                }
            }

        }


        public void UnregisterHotKeys()
        {
            try
            {
                WindowInteropHelper w = new WindowInteropHelper(this);
                foreach (int hotkeyid in HotKeyIds)
                {
                    Helper.UnregisterHotKey(w.Handle, hotkeyid);
                }
                HotKeyIds.Clear();
                ComponentDispatcher.ThreadPreprocessMessage -= ComponentDispatcher_ThreadPreprocessMessage;
            }
            catch (Exception ex)
            {
                System.Windows.MessageBox.Show(ex.ToString());
            }
        }

        public void RegisterHotKeys()
        {

            UnregisterHotKeys();
            ComponentDispatcher.ThreadPreprocessMessage += new ThreadMessageEventHandler(ComponentDispatcher_ThreadPreprocessMessage);
            int counter = 1;
            foreach (PlaceProfile profile in PlaceProfiles)
            {
                Keys key = Helper.IntegerToKey(counter);

                if (Settings.PlusAlt)
                {
                    key = key | Keys.Alt;
                }
                if (Settings.PlusControl)
                {
                    key = key | Keys.Control;
                }
                if (Settings.PlusShift)
                {
                    key = key | Keys.Shift;
                }
                RegisterHotKey(key);
                counter++;
            }
        }

        private void RegisterHotKey(Keys Key)
        {
            //Debug.Print("RegisterHotKey called {0}", Key.ToString());
            int modifiers = 0;
            if ((Key & Keys.Alt) == Keys.Alt)
                modifiers = modifiers | MOD_ALT;

            if ((Key & Keys.Control) == Keys.Control)
                modifiers = modifiers | MOD_CONTROL;

            if ((Key & Keys.Shift) == Keys.Shift)
                modifiers = modifiers | MOD_SHIFT;
            Keys k = Key & ~Keys.Control & ~Keys.Shift & ~Keys.Alt;
            int hookid = random.Next();
            HotKeyIds.Add(hookid);
            WindowInteropHelper w = new WindowInteropHelper(this);
            //Debug.Print("hookid = {0}", hookid);
            Helper.RegisterHotKey(w.Handle, hookid, (uint)modifiers, (uint)k);
        }


        #endregion



        #region DependencyProperty


        public string HotKeyCombinationString
        {
            get { return (string)GetValue(HotKeyCombinationStringProperty); }
            set { SetValue(HotKeyCombinationStringProperty, value); }
        }

        // Using a DependencyProperty as the backing store for HotKeyCombinationString.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HotKeyCombinationStringProperty =
            DependencyProperty.Register("HotKeyCombinationString", typeof(string), typeof(MainWindow), new UIPropertyMetadata(string.Empty));



        public bool NoPlaceProfiles
        {
            get { return (bool)GetValue(NoPlaceProfilesProperty); }
            set { SetValue(NoPlaceProfilesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for NoPlaceProfiles.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty NoPlaceProfilesProperty =
            DependencyProperty.Register("NoPlaceProfiles", typeof(bool), typeof(MainWindow), new UIPropertyMetadata(true));

        public bool HasPlaceProfiles
        {
            get { return (bool)GetValue(HasPlaceProfilesProperty); }
            set { SetValue(HasPlaceProfilesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for HasPlaceProfiles.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HasPlaceProfilesProperty =
            DependencyProperty.Register("HasPlaceProfiles", typeof(bool), typeof(MainWindow), new UIPropertyMetadata(false));

        public string SettingsFilename
        {
            get { return (string)GetValue(SettingsFilenameProperty); }
            set { SetValue(SettingsFilenameProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SettingsFilename.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SettingsFilenameProperty =
            DependencyProperty.Register("SettingsFilename", typeof(string), typeof(MainWindow), new UIPropertyMetadata(string.Empty));

        public ObservableCollection<PlaceProfile> PlaceProfiles
        {
            get { return (ObservableCollection<PlaceProfile>)GetValue(PlaceProfilesProperty); }
            set { SetValue(PlaceProfilesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PlaceProfiles.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PlaceProfilesProperty =
            DependencyProperty.Register("PlaceProfiles", typeof(ObservableCollection<PlaceProfile>), typeof(MainWindow), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, OnPlaceProfilesChanged));

        private static void OnPlaceProfilesChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue != null)
            {
                ((MainWindow)o).NoPlaceProfiles = ((ObservableCollection<PlaceProfile>)e.NewValue).Count == 0;
                ((MainWindow)o).HasPlaceProfiles = ((ObservableCollection<PlaceProfile>)e.NewValue).Count > 0;
            }
            else
            {
                ((MainWindow)o).NoPlaceProfiles = true;
                ((MainWindow)o).HasPlaceProfiles = false;
            }
        }

        public PlaceProfile SelectedPlaceProfile
        {
            get { return (PlaceProfile)GetValue(SelectedPlaceProfileProperty); }
            set { SetValue(SelectedPlaceProfileProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedPlaceProfile.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedPlaceProfileProperty =
            DependencyProperty.Register("SelectedPlaceProfile", typeof(PlaceProfile), typeof(MainWindow), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, OnProfileChanged));

        public WindowInfo SelectedDesiredWindowInfo
        {
            get { return (WindowInfo)GetValue(SelectedDesiredWindowInfoProperty); }
            set { SetValue(SelectedDesiredWindowInfoProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedDesiredWindowInfo.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedDesiredWindowInfoProperty =
            DependencyProperty.Register("SelectedDesiredWindowInfo", typeof(WindowInfo), typeof(MainWindow), new UIPropertyMetadata(null));

        public WindowInfo SelectedWindowInfo
        {
            get { return (WindowInfo)GetValue(SelectedWindowInfoProperty); }
            set { SetValue(SelectedWindowInfoProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedWindowInfo.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedWindowInfoProperty =
            DependencyProperty.Register("SelectedWindowInfo", typeof(WindowInfo), typeof(MainWindow), new UIPropertyMetadata(null));

        public WindowPlaceSettings Settings
        {
            get { return (WindowPlaceSettings)GetValue(SettingsProperty); }
            set { SetValue(SettingsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Settings.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SettingsProperty =
            DependencyProperty.Register("Settings", typeof(WindowPlaceSettings), typeof(MainWindow), new UIPropertyMetadata(null));

        #endregion

        #region Commands

        static void InitCommands()
        {
            AddProfile_ = new RoutedCommand("AddProfileCommand", typeof(MainWindow));
            CommandManager.RegisterClassCommandBinding(typeof(MainWindow), new CommandBinding(AddProfile_));
            RemoveProfile_ = new RoutedCommand("RemoveProfileCommand", typeof(MainWindow));
            CommandManager.RegisterClassCommandBinding(typeof(MainWindow), new CommandBinding(RemoveProfile_));
            SetAllToCurrentPositions_ = new RoutedCommand("SetAllToCurrentPositionsCommand", typeof(MainWindow));
            CommandManager.RegisterClassCommandBinding(typeof(MainWindow), new CommandBinding(SetAllToCurrentPositions_));

            EditWindowInfo_ = new RoutedCommand("EditWindowInfoCommand", typeof(MainWindow));
            CommandManager.RegisterClassCommandBinding(typeof(MainWindow), new CommandBinding(EditWindowInfo_));
            RemoveWindowInfo_ = new RoutedCommand("RemoveWindowInfoCommand", typeof(MainWindow));
            CommandManager.RegisterClassCommandBinding(typeof(MainWindow), new CommandBinding(RemoveWindowInfo_));
            SetToCurrentPosition_ = new RoutedCommand("SetToCurrentPositionCommand", typeof(MainWindow));
            CommandManager.RegisterClassCommandBinding(typeof(MainWindow), new CommandBinding(SetToCurrentPosition_));

            RetrieveLostWindow_ = new RoutedCommand("RetrieveLostWindowCommand", typeof(MainWindow));
            CommandManager.RegisterClassCommandBinding(typeof(MainWindow), new CommandBinding(RetrieveLostWindow_));

            StartAllWindows_ = new RoutedCommand("StartAllWindowsCommand", typeof(MainWindow));
            CommandManager.RegisterClassCommandBinding(typeof(MainWindow), new CommandBinding(StartAllWindows_));
        }

        private static RoutedCommand AddProfile_;
        public static RoutedCommand AddProfileCommand
        {
            get
            {
                return AddProfile_;
            }
        }

        private static RoutedCommand RemoveProfile_;
        public static RoutedCommand RemoveProfileCommand
        {
            get
            {
                return RemoveProfile_;
            }
        }

        private static RoutedCommand EditWindowInfo_;
        public static RoutedCommand EditWindowInfoCommand
        {
            get
            {
                return EditWindowInfo_;
            }
        }

        private static RoutedCommand RemoveWindowInfo_;
        public static RoutedCommand RemoveWindowInfoCommand
        {
            get
            {
                return RemoveWindowInfo_;
            }
        }

        private static RoutedCommand SetToCurrentPosition_;
        public static RoutedCommand SetToCurrentPositionCommand
        {
            get
            {
                return SetToCurrentPosition_;
            }
        }

        private static RoutedCommand SetAllToCurrentPositions_;
        public static RoutedCommand SetAllToCurrentPositionsCommand
        {
            get
            {
                return SetAllToCurrentPositions_;
            }
        }

        private static RoutedCommand RetrieveLostWindow_;
        public static RoutedCommand RetrieveLostWindowCommand
        {
            get
            {
                return RetrieveLostWindow_;
            }
        }

        private static RoutedCommand StartAllWindows_;
        public static RoutedCommand StartAllWindowsCommand
        {
            get
            {
                return StartAllWindows_;
            }
        }

        #endregion

        private void GetWindowCaptions_Click(object sender, RoutedEventArgs e)
        {
            this.WindowCaptionsList.ItemsSource = Helper.GetWindowInfos().Where(a => a.IsUseful && a.IsVisible == true).OrderBy(b => b.Caption);
        }

        #region WindowInfos

        private void New_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (this.PlaceProfiles.Count > 0)
            {
                WindowInfo info = (WindowInfo)e.Parameter;
                info.CaptionFilter = info.Caption;
                WindowInfoDialog wid = new WindowInfoDialog(info, true);
                if (wid.ShowDialog().Value == true)
                {
                    foreach (PlaceProfile pp in this.PlaceProfiles)
                    {
                        pp.WindowInfos.Add(WindowInfo.Copy(info));

                    }
                    this.SelectedPlaceProfile = null;
                    this.SelectedPlaceProfile = this.PlaceProfiles.First();
                }
            }
            else
            {
                System.Windows.MessageBox.Show("You must first add a PlaceProfile");
            }
        }

        private void New_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            //Debug.Print("CanExecute e.Parameter ={0}", e.Parameter != null ? e.Parameter.ToString() : "null");
            if (e.Parameter != null && e.Parameter.GetType() == typeof(WindowInfo))
            {
                e.CanExecute = true;
            }
            else e.CanExecute = false;
        }

        private void RemoveWindowInfo_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            WindowInfo info = (WindowInfo)e.Parameter;
            if (System.Windows.MessageBox.Show(string.Format("Remove WindowInfo '{0}'?", info.Caption), "Remove WindowPlace", MessageBoxButton.YesNo, MessageBoxImage.Exclamation, MessageBoxResult.No) == MessageBoxResult.Yes)
            {
                int index = this.SelectedPlaceProfile.WindowInfos.IndexOf(info);
                foreach (PlaceProfile pp in this.PlaceProfiles)
                {
                    pp.WindowInfos.RemoveAt(index);
                }
                this.SelectedPlaceProfile = null;
                this.SelectedPlaceProfile = this.PlaceProfiles.First();

            }
        }

        private void RemoveWindowInfo_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (e.Parameter != null && e.Parameter.GetType() == typeof(WindowInfo))
            {
                e.CanExecute = true;
            }
            else e.CanExecute = false;

        }

        private void EditWindow_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            WindowInfo info = (WindowInfo)e.Parameter;
            int index = this.SelectedPlaceProfile.WindowInfos.IndexOf(info);
            //Debug.Print("index of this WindowInfo = {0}", index);
            IEnumerable<WindowInfo> windows = Helper.GetWindowInfos().Where(a => a.IsUseful && a.IsVisible == true);
            info.FindThisWindow(windows);
            WindowInfoDialog wid = new WindowInfoDialog(info, false);
            if (wid.ShowDialog().Value == true)
            {
                //Debug.Print("now propogating change");
                foreach (PlaceProfile pp in this.PlaceProfiles)
                {
                    pp.WindowInfos[index].CaptionFilter = info.CaptionFilter;
                    pp.WindowInfos[index].AllowStartup = info.AllowStartup;
                    pp.WindowInfos[index].StartupArguments = info.StartupArguments;
                    pp.WindowInfos[index].IgnorePlacementAndSize = info.IgnorePlacementAndSize;
                    pp.WindowInfos[index].ModuleFullFilename = info.ModuleFullFilename;
                }
            }


        }

        private void EditWindow_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void SetToCurrentPosition_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            WindowInfo wi = (WindowInfo)e.Parameter;
            IEnumerable<WindowInfo> windows = WindowPlace.Common.Helper.GetWindowInfos().Where(a => a.IsUseful && a.IsVisible == true);
            wi.FindThisWindow(windows);
            if (wi.IsFound)
            {
                wi.CurrentRectangle = Helper.GetWindowRectangle(wi.hWnd);
            }
        }

        private void SetToCurrentPosition_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (e.Parameter != null && e.Parameter.GetType() == typeof(WindowInfo))
            {
                e.CanExecute = ((WindowInfo)e.Parameter).IsFound;
            }
            else e.CanExecute = false;
        }

        private void RetrieveLostWindow_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //Debug.Print("retriving lost window hWnd = {0}", SelectedWindowInfo.hWnd);
            IEnumerable<WindowInfo> windows = Helper.GetWindowInfos().Where(a => a.IsUseful && a.IsVisible == true);
            //Debug.Print("windows gotten ok");
            SelectedWindowInfo.FindThisWindow(windows, true);
            SelectedWindowInfo.Move(new Point());

        }

        private void RetrieveLostWindow_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (e.Parameter != null && e.Parameter.GetType() == typeof(WindowInfo))
            {
                e.CanExecute = true;
            }
            else e.CanExecute = false;
        }

        #endregion

        #region Profiles

        private static void OnProfileChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            //Debug.Print("OnProfileChanged");
            if (e.NewValue != null)
            {
                PlaceProfile pp = (PlaceProfile)e.NewValue;
                if (pp.IsValid)
                {
                    IEnumerable<WindowInfo> windows = WindowPlace.Common.Helper.GetWindowInfos().Where(a => a.IsUseful && a.IsVisible == true);

                    foreach (WindowInfo wi in pp.WindowInfos)
                    {
                        wi.FindThisWindow(windows);
                    }
                }
                else
                {
                    //System.Windows.MessageBox.Show("The PlaceProfile is not Valid. Perhaps a FilterCaption is not set on a WindowInfo");
                    ((MainWindow)o).notifier.Info = new PlaceProfileNotificationInfo("The PlaceProfile is not Valid. Perhaps a FilterCaption is not set on a WindowInfo", pp);
                    ((MainWindow)o).notifier.Notify();
                }
                pp.PlaceWindows();
                ((MainWindow)o).notifier.Info = new PlaceProfileNotificationInfo("Profile Changed Ok", pp);
                ((MainWindow)o).notifier.Notify();

            }
        }

        private void AddProfile_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            PlaceProfile pp = new PlaceProfile();
            pp.Label = string.Format("PlaceProfile #{0}", PlaceProfiles.Count + 1);

            if (this.PlaceProfiles.Count > 0)
            {
                this.PlaceProfiles.First().WindowInfos.ForEach(a => pp.WindowInfos.Add(WindowInfo.Copy(a)));
            }
            PlaceProfiles.Add(pp);

            pp.Index = this.PlaceProfiles.Count - 1;
            NoPlaceProfiles = false;
            HasPlaceProfiles = true;
            SelectedPlaceProfile = pp;

            UnregisterHotKeys();
            RegisterHotKeys();
        }

        private void AddProfile_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void RemoveProfile_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            PlaceProfile pp = (PlaceProfile)e.Parameter;
            if (System.Windows.MessageBox.Show(string.Format("Remove this PlaceProfile '{0}'?", pp.Label), "Remove PlaceProfile", MessageBoxButton.YesNo, MessageBoxImage.Exclamation) == MessageBoxResult.Yes)
            {
                UnregisterHotKeys();
                PlaceProfiles.Remove(pp);
                int counter = 0;
                foreach (PlaceProfile item in PlaceProfiles)
                {
                    item.Index = counter;
                    counter++;
                }

                if (PlaceProfiles.Count > 0)
                {
                    SelectedPlaceProfile = PlaceProfiles.First();
                }
                else
                {
                    SelectedPlaceProfile = null;
                    NoPlaceProfiles = true;
                    HasPlaceProfiles = false;
                }
                RegisterHotKeys();
            }
        }

        private void RemoveProfile_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (e.Parameter != null && e.Parameter.GetType() == typeof(PlaceProfile))
            {
                e.CanExecute = true;
            }
            else e.CanExecute = false;
        }

        private void RefreshProfile_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            PlaceProfile old = this.SelectedPlaceProfile;
            this.SelectedPlaceProfile = (PlaceProfile)e.Parameter;
            OnProfileChanged(this, new DependencyPropertyChangedEventArgs(SelectedPlaceProfileProperty, old, (PlaceProfile)e.Parameter));
        }

        private void RefreshProfile_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (e.Parameter != null && e.Parameter.GetType() == typeof(PlaceProfile))
            {
                e.CanExecute = true;
            }
            else e.CanExecute = false;
        }

        private void SetAllToCurrentPositions_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (System.Windows.MessageBox.Show("Are you sure you want to update this Profile with the Current Window Placements?", "Set All Window Placements", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                PlaceProfile pp = (PlaceProfile)e.Parameter;
                IEnumerable<WindowInfo> windows = Helper.GetWindowInfos().Where(a => a.IsUseful && a.IsVisible == true);
                foreach (WindowInfo wi in pp.WindowInfos)
                {
                    wi.FindThisWindow(windows);
                    if (wi.IsFound)
                    {
                        wi.CurrentRectangle = Common.Helper.GetWindowRectangle(wi.hWnd);
                    }
                }
            }

        }

        private void SetAllToCurrentPositions_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (e.Parameter != null && e.Parameter.GetType() == typeof(PlaceProfile))
            {
                e.CanExecute = ((PlaceProfile)e.Parameter).WindowInfos.Count > 0;
            }
            else e.CanExecute = false;
        }

        private void StartAllWindows_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Debug.Print("StartAllWindows_Executed");
            if (SelectedPlaceProfile.WindowInfos.All(a => a.AllowStartup == false))
            {
                System.Windows.MessageBox.Show("No WindowInfos AllowStartup. No action taken.", "Warning", MessageBoxButton.OK, MessageBoxImage.Information);
            }
            else
            {
                bool needwait = false;
                IEnumerable<WindowInfo> windows = WindowPlace.Common.Helper.GetWindowInfos().Where(a => a.IsUseful && a.IsVisible == true);


                foreach (WindowInfo windowinfo in SelectedPlaceProfile.WindowInfos)
                {
                    windowinfo.FindThisWindow(windows);
                    if (windowinfo.IsFound == true)
                    {
                        //Debug.Print("   {0} already started", windowinfo.Caption);
                    }
                    else
                    {
                        if (windowinfo.AllowStartup)
                        {
                            try
                            {
                                Debug.Print(">>>>>>>>>>>>>>{0} not started so start it with {1}", windowinfo.CaptionFilter, windowinfo.ModuleFullFilename);
                                Process p = new Process();
                                ProcessStartInfo si = new ProcessStartInfo(windowinfo.ModuleFullFilename, windowinfo.StartupArguments);
                                p.StartInfo = si;
                                p.Start();
                                needwait = true;
                            }
                            catch (Exception)
                            {
                                System.Windows.MessageBox.Show(string.Format("Unable to start '{0}'.\n\nArguments: '{1}'", windowinfo.ModuleFullFilename, windowinfo.StartupArguments), "Unable to Start Application", MessageBoxButton.OK, MessageBoxImage.Warning);
                            }
                        }
                    }
                }
                if (needwait)
                {
                    Debug.Print("sleeping for 1 second");
                    Thread.Sleep(this.Settings.StartupWaitTime);
                    NavigationCommands.Refresh.Execute(SelectedPlaceProfile, this);
                }
            }
        }

        private void StartAllWindows_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        #endregion

        #region Window Closing and Minimizing

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            notifier.Close();
            this.Settings.PlaceProfiles = this.PlaceProfiles.ToList();
            this.Settings.LastSession = DateTime.Now;

            WindowPlaceSettings.Save(this.Settings, this.SettingsFilename);
            WindowPlace.Properties.Settings.Default["SettingsFilename"] = this.SettingsFilename;

            Debug.Print("SettingsFilename set to {0}", WindowPlace.Properties.Settings.Default["SettingsFilename"]);

            WindowPlace.Properties.Settings.Default.Save();
            UnregisterHotKeys();
        }

        protected override void OnStateChanged(EventArgs e)
        {
            if (WindowState == System.Windows.WindowState.Minimized)
            {
                this.Hide();
            }
            base.OnStateChanged(e);
        }

        #endregion

        #region Open and Save Settings file

        private void Open_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (System.Windows.MessageBox.Show("Save current Settings?", "Save Settings", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                WindowPlaceSettings.Save(this.Settings, this.SettingsFilename);
            }

            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "xml files (*.xml)|*.xml|All files (*.*)|*.*";
            ofd.CheckFileExists = true;
            ofd.CheckPathExists = true;
            ofd.AutoUpgradeEnabled = true;
            ofd.Multiselect = false;

            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    this.SettingsFilename = ofd.FileName;
                    this.Settings = WindowPlaceSettings.Load(SettingsFilename);
                    this.PlaceProfiles = new ObservableCollection<PlaceProfile>(this.Settings.PlaceProfiles);
                }
                catch (Exception)
                {
                    System.Windows.MessageBox.Show("Unable to open this Settings file");
                    throw;
                }
            }

        }

        private void Open_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void SaveAs_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "xml files (*.xml)|*.xml";
            sfd.SupportMultiDottedExtensions = true;
            sfd.OverwritePrompt = true;
            sfd.AutoUpgradeEnabled = true;

            if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.SettingsFilename = sfd.FileName;
                WindowPlaceSettings.Save(this.Settings, this.SettingsFilename);
            }
        }

        private void SaveAs_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        #endregion

        private void NotifyIcon_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            this.Show();
            this.WindowState = System.Windows.WindowState.Normal;
        }
    }
}
